using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace TidhiGanitam.DataModel
{
    public class YogamuRoutineItem
    {
        private int m_Year;
        DateTime m_Date;
        private int m_SNo;
        ArrayList m_RaviRoutines;
        ArrayList m_ChandraRoutines;
        ArrayList m_DinamuRoutines;
        ArrayList m_YogamuDetails;
        Rasi m_YogamuTime;
        double m_CurrentYogamu;
        Enums.TidhiState m_PreviousYogamuState;

        public int Bhagam
        {
            get { return m_SNo; }
        }

        public DateTime Date
        {
            get { return m_Date; }
        }
        public Rasi YogamuTime
        {
            get { return m_YogamuTime; }
        }
        public ArrayList YogamuDetails
        {
            get
            { return m_YogamuDetails; }
            set
            {
                m_YogamuDetails = value;
            }
        }
        public double CurrentYogamu
        {
            get
            { return m_CurrentYogamu; }
            set
            { m_CurrentYogamu = value; }

        }
        public Enums.TidhiState PreviousYogamuState
        {
            get
            { return m_PreviousYogamuState; }
        }
        public YogamuRoutineItem(int SNo, int Year, DateTime Date, double currentYogamu, 
            Enums.TidhiState previousYogamuState, ArrayList RaviRoutines,
            ArrayList ChandraRoutines, ArrayList DinamuRoutines)
        {
            m_SNo = SNo;
            m_Year = Year;
            m_Date = Date;
            m_YogamuTime = new Rasi();
            m_YogamuDetails = new ArrayList();
            m_CurrentYogamu = currentYogamu;
            m_PreviousYogamuState = previousYogamuState;
            m_RaviRoutines = RaviRoutines;
            m_ChandraRoutines = ChandraRoutines;
            m_DinamuRoutines = DinamuRoutines;
        }
        public void Calculate(bool CheckingForEshyam, YogamuRoutineItem PreviousYogamuRoutine, DinamuRoutineItem PreviousDinamu)
        {
            double dSign = 1;
            Rasi SpastaChandra = new Rasi(((ChandraRoutineItem)m_ChandraRoutines[m_SNo]).SpastaChandrudu);
            Rasi SpastaRavi = new Rasi(((RaviRoutineItem)m_RaviRoutines[m_SNo]).MadyamaRavi);
            Rasi SpastaChandraGati = new Rasi(((ChandraRoutineItem)m_ChandraRoutines[m_SNo]).ChandraDinaGatiPhalam);
            Rasi SpastaRaviGati = new Rasi(((RaviRoutineItem)m_RaviRoutines[m_SNo]).Gati);
            DinamuRoutineItem CurrentDinamuRoutine = (DinamuRoutineItem)m_DinamuRoutines[m_SNo];

            #region Yogamu calculation
            // 1. Spasta Chandrudu + Spasta Ravi
            Rasi m_ChandraRaviSum = SpastaChandra + SpastaRavi;
            m_ChandraRaviSum.Refresh();
            // 2. Spasta Chandra Gati + Spasta Ravi Gati
            Rasi m_ChandraRaviGatiSum = SpastaChandraGati + SpastaRaviGati;
            m_ChandraRaviGatiSum.Refresh();
            // 3. Find Starting Yogamu
            Double dYogamuIndex = MathHelper.GetDegrees(((Rasi)(m_ChandraRaviSum / Constants.YogamuPramanam)).RawValue);
            if (m_SNo == 0 && !CheckingForEshyam)
            {
                m_CurrentYogamu = dYogamuIndex;
            }
            // 4. Find Advancement
            Rasi YogamuAdvancement = m_ChandraRaviSum - (Constants.YogamuPramanam * dYogamuIndex);
            Rasi YogamuRemining = new Rasi(YogamuAdvancement);
            // 5. If Advancement is more than 1/4 of Yogamu(0-3-20), subtract from 13-20; Sign here is Add
            //      Else we dont have to subtract from 13-20; Sign will be Subtract : -1

            // Note: Here we may have to do some adjustments as when previous yogamu is purti, we need not check
            // whether curernt yogamu advancement is more than quarter yogamu.
            if (YogamuAdvancement >= Constants.NakshatraPadaPramanam && (m_PreviousYogamuState != Enums.TidhiState.Purti) &&
                (m_PreviousYogamuState != Enums.TidhiState.NextdayEshyamAdjustment))
            {
                YogamuRemining = Constants.YogamuPramanam - YogamuAdvancement;
            }
            else
            {

                Rasi CurYgmInPrvDay = new Rasi();
                Rasi CurYgmInCrrDay = new Rasi();
                Rasi TotalYgm = new Rasi();

                if (m_PreviousYogamuState != Enums.TidhiState.Purti)
                {
                    CurYgmInPrvDay = PreviousDinamu.RojuPramanam - PreviousYogamuRoutine.YogamuTime;
                }
                else
                {
                    CurYgmInPrvDay = PreviousDinamu.RojuPramanam;
                }
                CurYgmInCrrDay = new Rasi(YogamuRemining / m_ChandraRaviGatiSum);
                TotalYgm = CurYgmInPrvDay + CurYgmInCrrDay;
                if (TotalYgm < new Rasi(0, 0, 35)) // || CurYgmInCrrDay > CurrentDinamuRoutine.Dinardhamu
                {
                    YogamuRemining = Constants.YogamuPramanam - YogamuAdvancement;
                }
                else
                {
                    dSign = -1;
                }
            }
            //Another adjustment is if when Yogamu

            // 6. Divide Yogamu remining with Gati sum
            Rasi YogamuTime = YogamuRemining / m_ChandraRaviGatiSum;

            // 7. Add this to dinardham. We consider the sign here
            m_YogamuTime = ((DinamuRoutineItem)m_DinamuRoutines[m_SNo]).Dinardhamu + (YogamuTime * dSign);

            //Just check yogamu time is -ve, make it +ve value
            if (m_YogamuTime < new Rasi(0, 0, 0))
            {
                m_YogamuTime = new Rasi(m_YogamuTime * -1); //just to make the value +ve
            }
            // if the
            if (m_CurrentYogamu < 0)
            {
                m_CurrentYogamu = dYogamuIndex;
            }

            // 8. Find out if Yogamu spans entire day
            if (m_YogamuTime > CurrentDinamuRoutine.RojuPramanam)
            {
                if (!CheckingForEshyam)
                {
                    YogamuDetails PurtiYogamu = new YogamuDetails(m_CurrentYogamu, Enums.TidhiState.Purti, m_Date, CurrentDinamuRoutine.RojuPramanam);
                    m_YogamuDetails.Add(PurtiYogamu);
                    m_PreviousYogamuState = Enums.TidhiState.Purti;
                }
            }
            else
            {
                //9. Yogamu completed. add this Yogamu to arraylist
                YogamuDetails NormalYogamu = new YogamuDetails(m_CurrentYogamu, Enums.TidhiState.Ending, m_Date, new Rasi(m_YogamuTime));
                m_YogamuDetails.Add(NormalYogamu);
                m_PreviousYogamuState = Enums.TidhiState.Ending;
                // Increment the tidhi and masamu
                IncrementYogamu();

                // 9. Find out if Eshyam is present
                Rasi StartYogamuTimeSpan = CurrentDinamuRoutine.RojuPramanam - m_YogamuTime;
                if (!CheckingForEshyam)
                {
                    if (CheckForEshyam(m_SNo, StartYogamuTimeSpan, CurrentYogamu, m_PreviousYogamuState))
                    {
                        Rasi EsyamuYogamuTime = Constants.YogamuPramanam / m_ChandraRaviGatiSum;
                        if (EsyamuYogamuTime < StartYogamuTimeSpan)
                        {
                            m_YogamuTime = new Rasi(EsyamuYogamuTime);
                            YogamuDetails EshyamYogamu = new YogamuDetails(m_CurrentYogamu, Enums.TidhiState.Eshyam, m_Date, new Rasi(m_YogamuTime));
                            m_YogamuDetails.Add(EshyamYogamu);
                            m_PreviousYogamuState = Enums.TidhiState.Eshyam;
                            // Increment the tidhi and masamu
                            IncrementYogamu();
                        }
                        else
                        {
                            m_PreviousYogamuState = Enums.TidhiState.NextdayEshyamAdjustment;
                        }
                    }
                }
            }
            #endregion


        }

        private void IncrementYogamu()
        {
            m_CurrentYogamu++; //Yogamu completed. so increment the Yogamu
            m_CurrentYogamu = m_CurrentYogamu % 27;
        }
        private bool CheckForEshyam(int CurrentPadakam, Rasi CurrentTime, double CurrentYogamu, Enums.TidhiState PreviousYogamuState)
        {
            bool RetValue = false;

            YogamuRoutineItem NextItem = new YogamuRoutineItem(CurrentPadakam + 1, m_Year, m_Date.AddDays(1), CurrentYogamu, PreviousYogamuState,
                m_RaviRoutines, m_ChandraRoutines, m_DinamuRoutines);
            NextItem.Calculate(true, this, (DinamuRoutineItem)m_DinamuRoutines[CurrentPadakam]);
            Rasi EndTime = new Rasi(NextItem.YogamuTime);
            if ((CurrentTime + EndTime) > new Rasi(0, 1, 30, 0))
            {
                RetValue = true;
            }
            return RetValue;
        }
    }
}
